﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.ComponentModel;
using System.Drawing;

namespace NF_Tools
{
    public enum RoomStatus
    {
        /// <summary>
        /// 空闲
        /// </summary>
        Idle = 0,
        /// <summary>
        /// 预定
        /// </summary>
        Reserve = 1,
        /// <summary>
        /// 占用
        /// </summary>
        Occupy = 2,
        /// <summary>
        /// 维修
        /// </summary>
        Repair = 3
    }


    public class RoomControl:Button, IContainerControl
    {
        private Control _activeControl;
        private Color _borderColor;
        
        private int _borderWidth = 4;

        [Category("NanQi"), Description("边框宽度")]
        public int BorderWidth
        {
            get { return _borderWidth; }
            set 
            {
                if (_borderWidth != value)
                {
                    _borderWidth = value; 
                    Invalidate();
                }
            }
        }

        private RoomStatus _status = RoomStatus.Idle;
        [Category("NanQi"), Description("包间状态")]
        public RoomStatus Status
        {
            get { return _status; }
            set
            {
                if (_status != value)
                {
                    _status = value;
                    Invalidate();
                }
            }
        }

        private string _roomType = "大";

        [Category("NanQi"), Description("包间类型")]
        public string RoomType
        {
            get { return _roomType; }
            set 
            {
                if (_roomType != value)
                {
                    _roomType = value; 
                    Invalidate();
                }
            }
        }

        private string _roomNo = "000";
        [Category("NanQi"), Description("包间编号")]
        public string RoomNo
        {
            get { return _roomNo; }
            set 
            {
                if (_roomNo != value)
                {
                    _roomNo = value; 
                    Invalidate();
                }
            }
        }

        private string _roomDesc = "空闲中";
        [Category("NanQi"), Description("包间状态描述")]
        public string RoomDesc
        {
            get { return _roomDesc; }
            set 
            {
                if (_roomDesc != value)
                {
                    _roomDesc = value; 
                    Invalidate();
                }
            }
        }

        private int _fixNumber = 0;
        [Category("Ternence"), Description("包间预订人数")]
        public int FixNumber
        {
            get { return _fixNumber; }
            set 
            { 
                if(_fixNumber != value)
                {
                    _fixNumber = value;
                    Invalidate();
                }
            }
        }

        [Category("Ternence"), Description("是否选中")]
        public bool Checked { get; set; }

        [Category("Ternence"), Description("包间ID")]
        public string RoomId { get; set; }
        
        [Category("Ternence"), Description("关联按钮的下标")]
        public int ToolsIndex { get; set; }

        private int _fixTime = 0;
        [Category("Ternence"), Description("预订的观影时长")]
        public int FixTime
        {
            get { return _fixTime; }
            set
            {
                if (_fixTime != value)
                {
                    _fixTime = value;
                    Invalidate();
                }
            }
        }

        private int _surplus = 0;
        [Category("Ternence"), Description("剩余观影时长")]
        public int Surplus
        {
            get { return _surplus; }
            set
            {
                if (_surplus != value)
                {
                    _surplus = value;
                    Invalidate();
                }
            }
        }

        private int _outTime = -1;
        [Category("Ternence"), Description("超出观影时长")]
        public int OutTime
        {
            get { return _outTime; }
            set
            {
                if (_outTime != value)
                {
                    _outTime = value;
                    Invalidate();
                }
            }
        }

        /// <summary>
        /// 开始计时时间
        /// </summary>
        [Category("Ternence"), Description("超出观影时长")]
        public string BeTime { get; set; }


        #region - event -

        private event EventHandler _fixNumberClick;
        [Category("Ternence"), Description("单击预订人数事件")]
        public event EventHandler FixNumberClick
        {
            add { _fixNumberClick += value; }
            remove { _fixNumberClick -= value; }
        }

         private event EventHandler _lodeToolsClick;
        [Category("Ternence"), Description("单击加载工具栏")]
         public event EventHandler LodeToolsClick
         {
             add { _lodeToolsClick += value; }
             remove { _lodeToolsClick -= value; }
         }

        #endregion

        #region field
        private float _typeFontSize = 14;
        private Font _typeFont = null;

        private float _noFontSize = 24;
        private Font _noFont = null;

        private float _descFontSize = 24;
        private Font _descFont = null;

        private float _timeLengthSize = 12;
        private Font _timeFont = null;

        private float _fixFontSize = 12;
        private Font _fixFont = null;

        private bool _isHovered = false;
        private bool _isPressed = false;
        private bool _isFocused = false;

        private Point _mouseLocation = Point.Empty;

        #endregion

        public RoomControl()
        {
            SetStyle(ControlStyles.AllPaintingInWmPaint |
                    ControlStyles.OptimizedDoubleBuffer |
                    ControlStyles.ResizeRedraw |
                    ControlStyles.UserPaint, true);

            this.Width = 250;
            this.Height = 180;

            _borderColor = Color.FromArgb(176, 176, 176);

            _typeFont = new Font("Segoe UI", _typeFontSize, FontStyle.Regular, GraphicsUnit.Pixel);
            _noFont = new Font("Segoe UI", _noFontSize, FontStyle.Bold, GraphicsUnit.Pixel);
            _descFont = new Font("Segoe UI", _descFontSize, FontStyle.Regular, GraphicsUnit.Pixel);
            _fixFont = new Font("Segoe UI", _fixFontSize, FontStyle.Regular, GraphicsUnit.Pixel);
            _timeFont = new Font("Segoe UI", _timeLengthSize, FontStyle.Regular, GraphicsUnit.Pixel);

            this.SizeChanged += new EventHandler(Room_SizeChanged);
        }

        void Room_SizeChanged(object sender, EventArgs e)
        {
            if (this.Width < 165)
            {
                this.Width = 165;
            }

            this.Height = (int)(this.Width * 0.624);

            var zoom = (this.Width - 165) / 7;

            _typeFont = new Font("Segoe UI", _typeFontSize + zoom, FontStyle.Regular, GraphicsUnit.Pixel);
            _noFont = new Font("Segoe UI", _noFontSize + zoom, FontStyle.Bold, GraphicsUnit.Pixel);
            _descFont = new Font("Segoe UI", _descFontSize + zoom, FontStyle.Regular, GraphicsUnit.Pixel);
            _timeFont = new Font("Segoe UI", _timeLengthSize + zoom, FontStyle.Regular, GraphicsUnit.Pixel);
        }

        protected override void OnPaint(PaintEventArgs pevent)
        {
            var g = pevent.Graphics;
            g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
            g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;

            g.Clear(this.Parent.BackColor);

            var offset_border = _borderWidth / 2;
            var offset_width = (int)(this.Width * 0.18);
            var offset_height = (int)(this.Height * 0.97);

            _borderColor = _isFocused ? SystemColors.Highlight : Color.FromArgb(176, 176, 176);

            using (var pen = new Pen(_borderColor, _borderWidth))
            {
                var arr_point = new Point[6];

                arr_point[0] = new Point(offset_width - offset_border, offset_height - offset_border- 30);
                arr_point[1] = new Point(offset_border, offset_height - offset_border - 30);
                arr_point[2] = new Point(offset_border, offset_border);
                arr_point[3] = new Point(this.Width - offset_border, offset_border);
                arr_point[4] = new Point(this.Width - offset_border, offset_height - offset_border - 30);
                arr_point[5] = new Point(this.Width - offset_width - offset_border, offset_height - offset_border - 30);

                if (_isPressed)
                {
                    if (_mouseLocation == Point.Empty)
                    {
                        arr_point[3] = new Point(arr_point[3].X - 2, arr_point[3].Y + 2);
                    }
                    else
                    {
                        if (_mouseLocation.X < this.Width / 3 && _mouseLocation.Y >= this.Height / 3 * 2)
                        {
                            arr_point[1] = new Point(arr_point[1].X + 2, arr_point[1].Y - 2);
                        }
                        else if (_mouseLocation.X < this.Width / 3 && _mouseLocation.Y < this.Height / 3)
                        {
                            arr_point[2] = new Point(arr_point[2].X + 2, arr_point[2].Y + 2);
                        }
                        else if (_mouseLocation.X >= this.Width / 3 * 2 && _mouseLocation.Y < this.Height / 3)
                        {
                            arr_point[3] = new Point(arr_point[3].X - 2, arr_point[3].Y + 2);
                        }
                        else if (_mouseLocation.X >= this.Width / 3 * 2 && _mouseLocation.Y >= this.Height / 3 * 2)
                        {
                            arr_point[4] = new Point(arr_point[4].X - 2, arr_point[4].Y - 2);
                        }
                        //
                        else if (_mouseLocation.X < this.Width / 2 
                            && _mouseLocation.Y >= this.Height / 3
                            && _mouseLocation.Y < this.Height / 3 * 2)
                        {
                            arr_point[1] = new Point(arr_point[1].X + 2, arr_point[1].Y - 2);
                            arr_point[2] = new Point(arr_point[2].X + 2, arr_point[2].Y + 2);
                        }
                        else if (_mouseLocation.Y < this.Height / 2
                            && _mouseLocation.X >= this.Width / 3
                            && _mouseLocation.X < this.Width / 3 * 2)
                        {
                            arr_point[2] = new Point(arr_point[2].X + 2, arr_point[2].Y + 2);
                            arr_point[3] = new Point(arr_point[3].X - 2, arr_point[3].Y + 2);
                        }
                        else if (_mouseLocation.X >= this.Width / 2
                            && _mouseLocation.Y >= this.Height / 3
                            && _mouseLocation.Y < this.Height / 3 * 2)
                        {
                            arr_point[3] = new Point(arr_point[3].X - 2, arr_point[3].Y + 2);
                            arr_point[4] = new Point(arr_point[4].X - 2, arr_point[4].Y - 2);
                        }
                        else if (_mouseLocation.Y >= this.Height / 2
                            && _mouseLocation.X >= this.Width / 3
                            && _mouseLocation.X < this.Width / 3 * 2)
                        {
                            //arr_point[1] = new Point(arr_point[1].X + 2, arr_point[1].Y - 2);
                            //arr_point[4] = new Point(arr_point[4].X - 2, arr_point[4].Y - 2);
                        }
                    }
                }

                g.DrawLines(pen, arr_point);
            }

            using (var pen = GetPenByStatus())
            {
                var margin_width = _borderWidth * 2;

                if (_isPressed
                    && _mouseLocation.Y >= this.Height / 2
                    && _mouseLocation.X >= this.Width / 3
                    && _mouseLocation.X < this.Width / 3 * 2)
                {
                    g.DrawLine(pen, offset_width - offset_border + margin_width, offset_height - offset_border - 2 -30,
                        this.Width - offset_width - offset_border - margin_width, offset_height - offset_border - 2 -30);
                }
                else
                {
                    g.DrawLine(pen, offset_width - offset_border + margin_width, offset_height - offset_border -30 ,
                        this.Width - offset_width - offset_border - margin_width, offset_height - offset_border -30 );
                }
            }
            if (_fixNumber != 0)
            {
                var fix = TextRenderer.MeasureText(_fixNumber + " 人已预订", _noFont);
                TextRenderer.DrawText(g, _fixNumber + " 人已预订", _fixFont,
                    new Point(10, 10), Color.FromArgb(90, 90, 90));
            }

            var typeTextSize = TextRenderer.MeasureText(_roomType, _typeFont);
            var marginRoomType = _borderWidth / 2;
            TextRenderer.DrawText(g, _roomType, _typeFont,
                new Point(this.Width - typeTextSize.Width - marginRoomType, offset_border + marginRoomType),
                Color.FromArgb(90, 90, 90));

            var offset = 10;

            var noTextSize = TextRenderer.MeasureText(_roomNo, _noFont);
            TextRenderer.DrawText(g, _roomNo, _noFont,
                new Point((this.Width - noTextSize.Width) / 2, (this.Height + offset_border + typeTextSize.Height - offset) / 5),
                Color.FromArgb(90, 90, 90));

            if (_status == RoomStatus.Repair)
                _roomDesc = "维护中";
            else if (_status == RoomStatus.Occupy)
                _roomDesc = "占用中";
            else
                _roomDesc = "空闲中";

            var descTextSize = TextRenderer.MeasureText(_roomDesc, _descFont);
            TextRenderer.DrawText(g, _roomDesc, _descFont,
                new Point((this.Width - descTextSize.Width) / 2,
                    (this.Height + offset_border + typeTextSize.Height + noTextSize.Height - offset) / 3),
                GetColorByStatus());

            if (_fixTime > 0)
            {
                var fixTime = "预订：" + _fixTime + " 分钟";
                var fixtimeLength = TextRenderer.MeasureText(fixTime, _timeFont);
                TextRenderer.DrawText(g, fixTime, _timeFont, new Point(25, this.Height - offset - 50 - offset_border), Color.FromArgb(44, 202, 55));



                if (_outTime > 0)
                {
                    var outtime = "超时：" + _outTime + " 分钟";
                    var outTimeLengt = TextRenderer.MeasureText(outtime, _timeFont);
                    TextRenderer.DrawText(g, outtime, _timeFont, new Point(90 + outTimeLengt.Width / 2, this.Height - offset - 50 - offset_border), Color.FromArgb(238, 64, 0));
                }
                else
                {
                    var surTime = "剩余：" + Surplus + " 分钟";
                    var timeLength = TextRenderer.MeasureText(surTime, _timeFont);
                    TextRenderer.DrawText(g, surTime, _timeFont, new Point(90 + timeLength.Width / 2, this.Height - offset - 50 - offset_border), Color.FromArgb(44, 202, 55));
                }
            }
        }

        protected override void OnMouseClick(MouseEventArgs e)
        {
            if (e.X < 74 && e.Y < 26 && _fixNumber != 0)
            {
                _fixNumberClick.Invoke(this, e);
            }
            else
            {
                _lodeToolsClick.Invoke(this, e);
            }

            base.OnMouseClick(e);
        }


        #region Focus Methods

        protected override void OnGotFocus(EventArgs e)
        {
            _isFocused = true;
            Invalidate();

            base.OnGotFocus(e);
        }

        protected override void OnLostFocus(EventArgs e)
        {
            _isFocused = false;
            _isHovered = false;
            _isPressed = false;
            Invalidate();
            base.OnLostFocus(e);
            //this.Controls.Clear();
        }

        protected override void OnEnter(EventArgs e)
        {
            _isFocused = true;
            Invalidate();

            base.OnEnter(e);
        }

        protected override void OnLeave(EventArgs e)
        {
            _isFocused = false;
            _isHovered = false;
            _isPressed = false;
            Invalidate();

            base.OnLeave(e);
        }

        #endregion

        #region prive method
        private Pen GetPenByStatus()
        {
            return new Pen(GetColorByStatus(), (int)(_borderWidth / 0.4));
        }
        private Color GetColorByStatus()
        {
            Color color = Color.FromArgb(44, 202, 55);

            switch (_status)
            {
                case RoomStatus.Idle:
                    color = Color.FromArgb(44, 202, 55);
                    break;
                //case RoomStatus.Reserve:
                //    color = Color.FromArgb(246, 163, 18);
                //    break;
                case RoomStatus.Occupy:
                    color = Color.FromArgb(176, 176, 176);
                    break;
                case RoomStatus.Repair:
                    color = Color.FromArgb(232, 66, 66);
                    break;
                default:
                    color = Color.FromArgb(44, 202, 55);
                    break;
            }

            return color;
        }
        #endregion

        #region IContainerControl 成员

        public bool ActivateControl(Control active)
        {
            if (Controls.Contains(active))
            {
                active.Select();
                _activeControl = active;
                
                return true;
            }

            return false;
        }

        public Control ActiveControl
        {
            get { return _activeControl; }
            set { _activeControl = value; }
        }

        #endregion

        #region Keyboard Methods

        protected override void OnKeyDown(KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Space)
            {
                _isHovered = true;
                _mouseLocation = Point.Empty;
                _isPressed = true;
                Invalidate();
            }

            base.OnKeyDown(e);
        }

        protected override void OnKeyUp(KeyEventArgs e)
        {
            _isHovered = false;
            _isPressed = false;
            Invalidate();

            base.OnKeyUp(e);
        }

        #endregion

        #region Mouse Methods

        protected override void OnMouseEnter(EventArgs e)
        {
            _isHovered = true;
            this.Cursor = System.Windows.Forms.Cursors.Hand;
            Invalidate();
            base.OnMouseEnter(e);
        }

        protected override void OnMouseDown(MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                _mouseLocation = e.Location;
                _isPressed = true;
                Invalidate();
            }

            base.OnMouseDown(e);
        }

        protected override void OnMouseUp(MouseEventArgs e)
        {
            _isPressed = false;
            Invalidate();

            base.OnMouseUp(e);
        }

        protected override void OnMouseLeave(EventArgs e)
        {
            _isHovered = false;
            Invalidate();

            base.OnMouseLeave(e);
        }

        #endregion
    }
}
